package com.example.system.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.example.common.enums.CodeEnum;
import com.example.common.exception.ServiceException;
import com.example.common.utils.R;
import com.example.common.utils.SnowFlake;
import com.example.system.dto.PaymentDTO;
import com.example.system.entity.Order;
import com.example.system.entity.Payment;
import com.example.system.mapper.OrderMapper;
import com.example.system.mapper.PatientMapper;
import com.example.system.mapper.PaymentMapper;
import com.example.system.service.IOrderService;
import com.example.system.service.IUserService;
import org.apache.commons.lang3.ObjectUtils;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.Calendar;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 王鹤蒲
 * @since 2024-02-03
 */
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private PaymentMapper paymentMapper;

    @Autowired
    private PatientMapper patientMapper;

    @Autowired
    private IUserService iUserService;

    @Autowired
    private SnowFlake snowFlake;

    @Autowired
    private JavaMailSender javaMailSender;

    @Value("${spring.mail.username}")
    private String from;

    @Autowired
    private Scheduler scheduler;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;



    @Override
    public R createOrder(Order order)  {
        LocalDateTime createTime = LocalDateTime.now();
        String orderNo = "od" + snowFlake.nextId();
        order.setOrderNo(orderNo).setCreateBy(iUserService.getCurrentLoginUser().getUserName()).setCreateTime(createTime);
        orderMapper.insert(order);
        if ("1".equals(order.getType())) {
            PaymentDTO paymentDTO = new PaymentDTO();
            paymentDTO.setOrderNo(orderNo).setAmount(order.getAmount()).setSubject("挂号");
            paymentDTO.setSubject("医币充值");
            return R.success(paymentDTO);
        }
        String email=patientMapper.selectEmailByPatientId(order.getPatientId());
        String subject="挂号订单支付提醒";
        String message="您的挂号订单（订单号："+orderNo+"）创建成功，请在规定时间内完成支付。";
        sendMailReminder(email,subject,message);
        redisTemplate.opsForValue().set(orderNo, "created");
        redisTemplate.expire(orderNo, 10, TimeUnit.MINUTES);
        try {
        Date currentDate = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(currentDate);
        calendar.add(Calendar.MINUTE, 2);
        JobKey jobKey=JobKey.jobKey("cancelOrder:"+orderNo,"cancelOrder");
        Class<Job> jobClass=(Class<Job>)Class.forName("com.example.framework.job.OrderStatusMonitoringJob");
        JobDetail jobDetail=JobBuilder.newJob(jobClass).withIdentity(jobKey).withDescription("cancelOrder:"+orderNo).build();
        jobDetail.getJobDataMap().put("orderNo",orderNo);
        jobDetail.getJobDataMap().put("email",email);
        TriggerKey triggerKey=TriggerKey.triggerKey("cancelOrder:"+orderNo,"cancelOrder");
        Trigger trigger=TriggerBuilder.newTrigger().withIdentity(triggerKey).startAt(calendar.getTime()).withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInMinutes(2).repeatForever().withMisfireHandlingInstructionNowWithExistingCount()).build();
        scheduler.scheduleJob(jobDetail,trigger);
        } catch (ClassNotFoundException e) {
            throw new ServiceException(CodeEnum.TIMING_TASK_ERROR.getCode(),CodeEnum.TIMING_TASK_ERROR.getMsg());
        } catch (SchedulerException e) {
            throw new ServiceException(CodeEnum.TIMING_TASK_ERROR.getCode(),CodeEnum.TIMING_TASK_ERROR.getMsg());
        }
        return R.success();
    }

    @Override
    public void sendMailReminder(String email, String subject, String message) {
        SimpleMailMessage simpleMailMessage=new SimpleMailMessage();
        simpleMailMessage.setFrom(from);
        simpleMailMessage.setTo(email);
        simpleMailMessage.setSubject(subject);
        simpleMailMessage.setText(message);
        simpleMailMessage.setSentDate(new Date());
        javaMailSender.send(simpleMailMessage);
    }


    @Override
    public R selectAll(int currentPage, int pageSize, String orderNo, String status, String type, String createBy, LocalDate createDate) {
        Page<Order> page = new Page<>(currentPage, pageSize);
        LambdaQueryWrapper<Order> orderLambdaQueryWrapper = new LambdaQueryWrapper<>();
        orderLambdaQueryWrapper.like(ObjectUtil.isNotEmpty(orderNo), Order::getOrderNo, orderNo);
        if (!"2".equals(status)) {
            orderLambdaQueryWrapper.eq(ObjectUtil.isNotEmpty(status), Order::getStatus, status);
        } else {
            orderLambdaQueryWrapper.and(wrapper -> wrapper.eq(Order::getStatus, "-1").or().eq(Order::getStatus, "1"));
        }
        orderLambdaQueryWrapper.eq(ObjectUtil.isNotEmpty(type), Order::getType, type);
        orderLambdaQueryWrapper.like(ObjectUtil.isNotEmpty(createBy), Order::getCreateBy, createBy);
        orderLambdaQueryWrapper.like(ObjectUtil.isNotEmpty(createDate), Order::getCreateTime, createDate);
        return R.success(orderMapper.selectPage(page, orderLambdaQueryWrapper));
    }

    @Override
    public R selectOrderDetail(String orderNo) {
        LambdaQueryWrapper<Order> orderLambdaQueryWrapper = new LambdaQueryWrapper<>();
        orderLambdaQueryWrapper.eq(Order::getOrderNo, orderNo);
        orderLambdaQueryWrapper.eq(Order::getDelFlag, "0");
        Order order = orderMapper.selectOne(orderLambdaQueryWrapper);
        LambdaQueryWrapper<Payment> paymentLambdaQueryWrapper = new LambdaQueryWrapper<>();
        paymentLambdaQueryWrapper.eq(Payment::getOrderNo, orderNo);
        paymentLambdaQueryWrapper.eq(Payment::getDelFlag, "0");
        List<Payment> paymentList = paymentMapper.selectList(paymentLambdaQueryWrapper);
        order.setPaymentList(paymentList);
        return R.success(order);
    }

    @Override
    public R cancelOrder(String orderNo) {
        LambdaQueryWrapper<Order> orderLambdaQueryWrapper = new LambdaQueryWrapper<>();
        orderLambdaQueryWrapper.eq(Order::getDelFlag, "0");
        orderLambdaQueryWrapper.eq(Order::getOrderNo, orderNo);
        String orderStatus=orderMapper.selectOne(orderLambdaQueryWrapper).getStatus();
        if ("0".equals(orderStatus)) {
            LocalDateTime updateTime = LocalDateTime.now();
            LambdaUpdateWrapper<Order> orderLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
            orderLambdaUpdateWrapper.eq(Order::getDelFlag, "0");
            orderLambdaUpdateWrapper.eq(Order::getOrderNo, orderNo);
            orderLambdaUpdateWrapper.set(Order::getStatus, "-1");
            orderLambdaUpdateWrapper.set(Order::getUpdateBy, iUserService.getCurrentLoginUser().getUserName());
            orderLambdaUpdateWrapper.set(Order::getUpdateTime, updateTime);
            orderMapper.update(new Order(),orderLambdaUpdateWrapper);
            return R.success();
        } else if("1".equals(orderStatus)){
            //todo 取消订单、退款
            return R.success();
        }else{
            return R.error();
        }
    }

    @Override
    public R cancelBatch(String[] orderNoList) {
        return R.success();
    }

    @Override
    public R deletelOrder(String orderNo) {
        return R.success();
    }

    @Override
    public R deleteBatch(String[] orderNoList) {
        return R.success();
    }

    @Override
    public R findPatientOrderList(int currentPage, int pageSize, Integer userId, String orderDate, String status) {
        Page<Order> page=new Page<>(currentPage,pageSize);
        return R.success(orderMapper.findPatientOrderList(page,userId,orderDate,status));
    }

    @Override
    public R findOrderDetailListByPage(int currentPage,int pageSize, Integer userId, String workDate, String status) {
        Page<Order> page=new Page<>(currentPage,pageSize);
        return R.success(orderMapper.findOrderDetailListByPage(page,userId,workDate,status));
    }

    @Override
    public R serviceEvaluation(String orderNo, Integer rate, String feedback) {
        LambdaUpdateWrapper<Order> lambdaUpdateWrapper=new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.eq(Order::getOrderNo,orderNo);
        lambdaUpdateWrapper.set(Order::getRate,rate);
        lambdaUpdateWrapper.set(Order::getFeedback,feedback);
        lambdaUpdateWrapper.set(Order::getUpdateBy,iUserService.getCurrentLoginUser().getUserName());
        lambdaUpdateWrapper.set(Order::getUpdateTime,LocalDateTime.now());
        orderMapper.update(new Order(),lambdaUpdateWrapper);
        return R.success();
    }


}
